﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Core.DBInterfaces;
using Core.PageEntities;
using Core.SupportEntities;
using System.Linq.Expressions;

namespace MSSqlDataBase.Repository
{
    public sealed class DbRepository<T> : IDbRepository where T : DbContext, new()
    {
        private List<IGenericRepository> _repositoryList;
        private DbContext _dbContext = new T();

        public DbRepository()
        {           
            _repositoryList = new List<IGenericRepository>();
        }

        #region Public methods and properties

        public bool IsCreateProxy
        {
            get
            {
                return this._dbContext.Configuration.ProxyCreationEnabled;
            }
            set
            {
                this._dbContext.Configuration.ProxyCreationEnabled = value;
            }
        }

        public IEnumerable<TEntity> Get<TEntity>(
            Expression<Func<TEntity, bool>> filter = null,
            string includeProperties = "",
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
            int skip = 0, int take = 0) where TEntity : class
        {
            var repository = GetRepository<TEntity>();
            var query = repository.Get(filter, orderBy, skip, take, includeProperties);
            return query;
        }
        public TEntity GetById<TEntity>(object id) where TEntity : class
        {
            var repository = GetRepository<TEntity>();
            var query = repository.GetById(id);
            return query;
        }
        public void Insert<TEntity>(TEntity entity) where TEntity : class
        {
            var repository = GetRepository<TEntity>();
            repository.Insert(entity);
        }
        public void Delete<TEntity>(object id) where TEntity : class
        {
            var repository = GetRepository<TEntity>();
            repository.Delete(id);
        }
        public void Delete<TEntity>(TEntity entityToDelete) where TEntity : class
        {
            var repository = GetRepository<TEntity>();
            repository.Delete(entityToDelete);
        }
        public void Update<TEntity>(TEntity entityToUpdate) where TEntity : class
        {
            var repository = GetRepository<TEntity>();
            repository.Update(entityToUpdate);
        }


        public int Save()
        {
            var counter = 0;
            counter = _dbContext.SaveChanges();
            return counter;
        }

        #endregion

        private IGenericRepository<C> GetRepository<C>() where C : class
        {
            var repository = (IGenericRepository<C>)_repositoryList.SingleOrDefault(x => x.POCOType == typeof(C));

            if (repository == null)
            {
                repository = new GenericRepository<C>(_dbContext);
                _repositoryList.Add(repository);
            }

            return repository;
        }

        #region Dispose methods

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if (disposing)
            {
                _dbContext.Dispose();
                _dbContext = null;
            }
        }
        ~DbRepository()
        {
            Dispose(false);
        }
        #endregion
    }
}
